]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Add a confirmation dialog for display changes
authorGiovanni Campagna <gcampagna@src.gnome.org>
Sat, 17 Aug 2013 15:42:39 +0000 (17:42 +0200)
committerGiovanni Campagna <gcampagn@redhat.com>
Tue, 20 Aug 2013 10:03:13 +0000 (12:03 +0200)
Unfortunately, display configuration can and does fail, due
to unspecified HW constraints, drivers bugs, unsupported exotic
configurations or just bad luck.
So when the user makes a change in the control center, show
a dialog asking him if it looks OK, and revert back after 20 seconds
otherwise.

https://bugzilla.gnome.org/show_bug.cgi?id=706208

js/ui/windowManager.js
src/gnome-shell-plugin.c
src/shell-wm-private.h
src/shell-wm.c
src/shell-wm.h

index d6b0b7aebc1dbd6382f573174086b9b109a368fe..96270a479a4ddbc2abf25d7da6a8e7cdbce69334 100644 (file)
@@ -6,12 +6,14 @@ const Gio = imports.gi.Gio;
 const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
+const Pango = imports.gi.Pango;
 const St = imports.gi.St;
 const Shell = imports.gi.Shell;
 
 const AltTab = imports.ui.altTab;
 const WorkspaceSwitcherPopup = imports.ui.workspaceSwitcherPopup;
 const Main = imports.ui.main;
+const ModalDialog = imports.ui.modalDialog;
 const Tweener = imports.ui.tweener;
 
 const SHELL_KEYBINDINGS_SCHEMA = 'org.gnome.shell.keybindings';
@@ -20,6 +22,107 @@ const DIM_BRIGHTNESS = -0.3;
 const DIM_TIME = 0.500;
 const UNDIM_TIME = 0.250;
 
+const DISPLAY_REVERT_TIMEOUT = 20; // in seconds - keep in sync with mutter
+const ONE_SECOND = 1000; // in ms
+
+const DisplayChangeDialog = new Lang.Class({
+    Name: 'DisplayChangeDialog',
+    Extends: ModalDialog.ModalDialog,
+
+    _init: function(wm) {
+        this.parent({ styleClass: 'prompt-dialog' });
+
+        this._wm = wm;
+
+        let mainContentBox = new St.BoxLayout({ style_class: 'prompt-dialog-main-layout',
+                                                vertical: false });
+        this.contentLayout.add(mainContentBox,
+                               { x_fill: true,
+                                 y_fill: true });
+
+        let icon = new St.Icon({ icon_name: 'preferences-desktop-display-symbolic' });
+        mainContentBox.add(icon,
+                           { x_fill:  true,
+                             y_fill:  false,
+                             x_align: St.Align.END,
+                             y_align: St.Align.START });
+
+        let messageBox = new St.BoxLayout({ style_class: 'prompt-dialog-message-layout',
+                                            vertical: true });
+        mainContentBox.add(messageBox,
+                           { expand: true, y_align: St.Align.START });
+
+        let subjectLabel = new St.Label({ style_class: 'prompt-dialog-headline',
+                                            text: _("Do you want to keep these display settings?") });
+        messageBox.add(subjectLabel,
+                       { y_fill:  false,
+                         y_align: St.Align.START });
+
+        this._countDown = DISPLAY_REVERT_TIMEOUT;
+        let message = this._formatCountDown();
+        this._descriptionLabel = new St.Label({ style_class: 'prompt-dialog-description',
+                                                text: this._formatCountDown() });
+        this._descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
+        this._descriptionLabel.clutter_text.line_wrap = true;
+
+        messageBox.add(this._descriptionLabel,
+                       { y_fill:  true,
+                         y_align: St.Align.START });
+
+        /* Translators: this and the following message should be limited in lenght,
+           to avoid ellipsizing the labels.
+        */
+        this._cancelButton = this.addButton({ label: _("Revert Settings"),
+                                              action: Lang.bind(this, this._onFailure),
+                                              key: Clutter.Escape },
+                                            { expand: true, x_fill: false, x_align: St.Align.START });
+        this._okButton = this.addButton({ label:  _("Keep Changes"),
+                                          action: Lang.bind(this, this._onSuccess),
+                                          default: true },
+                                        { expand: false, x_fill: false, x_align: St.Align.END });
+
+        this._timeoutId = Mainloop.timeout_add(ONE_SECOND, Lang.bind(this, this._tick));
+    },
+
+    close: function(timestamp) {
+        if (this._timeoutId > 0) {
+            Mainloop.source_remove(this._timeoutId);
+            this._timeoutId = 0;
+        }
+
+        this.parent(timestamp);
+    },
+
+    _formatCountDown: function() {
+        let fmt = ngettext("Settings changes will revert in %d second",
+                           "Settings changes will revert in %d seconds");
+        return fmt.format(this._countDown);
+    },
+
+    _tick: function() {
+        this._countDown--;
+
+        if (this._countDown == 0) {
+            /* mutter already takes care of failing at timeout */
+            this._timeoutId = 0;
+            this.close();
+            return false;
+        }
+
+        this._descriptionLabel.text = this._formatCountDown();
+        return true;
+    },
+
+    _onFailure: function() {
+        this._wm.complete_display_change(false);
+        this.close();
+    },
+
+    _onSuccess: function() {
+        this._wm.complete_display_change(true);
+        this.close();
+    },
+});
 
 const WindowDimmer = new Lang.Class({
     Name: 'WindowDimmer',
@@ -306,6 +409,7 @@ const WindowManager = new Lang.Class({
         this._shellwm.connect('map', Lang.bind(this, this._mapWindow));
         this._shellwm.connect('destroy', Lang.bind(this, this._destroyWindow));
         this._shellwm.connect('filter-keybinding', Lang.bind(this, this._filterKeybinding));
+        this._shellwm.connect('confirm-display-change', Lang.bind(this, this._confirmDisplayChange));
 
         this._workspaceSwitcherPopup = null;
         this.setCustomKeybindingHandler('switch-to-workspace-left',
@@ -1056,4 +1160,9 @@ const WindowManager = new Lang.Class({
             workspace.activate_with_focus (window, global.get_current_time());
         }
     },
+
+    _confirmDisplayChange: function() {
+        let dialog = new DisplayChangeDialog(this._shellwm);
+        dialog.open();
+    },
 });
index 3470637fa69b864e960a568756a779a9c60c9147..6571b39238a1a9e561671c276a80984686f6b03c 100644 (file)
@@ -75,6 +75,9 @@ static gboolean              gnome_shell_plugin_xevent_filter (MetaPlugin *plugi
 
 static gboolean              gnome_shell_plugin_keybinding_filter (MetaPlugin *plugin,
                                                                    MetaKeyBinding *binding);
+
+static void gnome_shell_plugin_confirm_display_change (MetaPlugin *plugin);
+
 static const MetaPluginInfo *gnome_shell_plugin_plugin_info   (MetaPlugin *plugin);
 
 
@@ -132,6 +135,9 @@ gnome_shell_plugin_class_init (GnomeShellPluginClass *klass)
 
   plugin_class->xevent_filter     = gnome_shell_plugin_xevent_filter;
   plugin_class->keybinding_filter = gnome_shell_plugin_keybinding_filter;
+
+  plugin_class->confirm_display_change = gnome_shell_plugin_confirm_display_change;
+
   plugin_class->plugin_info       = gnome_shell_plugin_plugin_info;
 }
 
@@ -399,6 +405,12 @@ gnome_shell_plugin_keybinding_filter (MetaPlugin     *plugin,
   return _shell_wm_filter_keybinding (get_shell_wm (), binding);
 }
 
+static void
+gnome_shell_plugin_confirm_display_change (MetaPlugin *plugin)
+{
+  _shell_wm_confirm_display_change (get_shell_wm ());
+}
+
 static const
 MetaPluginInfo *gnome_shell_plugin_plugin_info (MetaPlugin *plugin)
 {
index 6fc9348cebdb9add6e74cb8b366d1b53d8442b80..bc9d4c317c029cc8d9718b0a7be293fbfc2cb50d 100644 (file)
@@ -38,6 +38,8 @@ void _shell_wm_kill_switch_workspace (ShellWM             *wm);
 gboolean _shell_wm_filter_keybinding (ShellWM             *wm,
                                       MetaKeyBinding      *binding);
 
+void _shell_wm_confirm_display_change (ShellWM            *wm);
+
 G_END_DECLS
 
 #endif /* __SHELL_WM_PRIVATE_H__ */
index 08aceb7f20cefc2d93c1035a45d1a3e127008baa..20f101ed4abaf22755e6f568ca2522d7b2f7ca9e 100644 (file)
@@ -27,6 +27,7 @@ enum
   KILL_SWITCH_WORKSPACE,
   KILL_WINDOW_EFFECTS,
   FILTER_KEYBINDING,
+  CONFIRM_DISPLAY_CHANGE,
 
   LAST_SIGNAL
 };
@@ -124,6 +125,13 @@ shell_wm_class_init (ShellWMClass *klass)
                   g_signal_accumulator_true_handled, NULL, NULL,
                   G_TYPE_BOOLEAN, 1,
                   META_TYPE_KEY_BINDING);
+  shell_wm_signals[CONFIRM_DISPLAY_CHANGE] =
+    g_signal_new ("confirm-display-change",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST,
+                  0,
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
 }
 
 void
@@ -219,6 +227,20 @@ shell_wm_completed_destroy (ShellWM         *wm,
   meta_plugin_destroy_completed (wm->plugin, actor);
 }
 
+/**
+ * shell_wm_complete_display_change:
+ * @wm: the ShellWM
+ * @ok: if the new configuration was OK
+ *
+ * The plugin must call this after the user responded to the confirmation dialog.
+ */
+void
+shell_wm_complete_display_change (ShellWM  *wm,
+                                  gboolean  ok)
+{
+  meta_plugin_complete_display_change (wm->plugin, ok);
+}
+
 void
 _shell_wm_kill_switch_workspace (ShellWM      *wm)
 {
@@ -287,6 +309,12 @@ _shell_wm_filter_keybinding (ShellWM             *wm,
   return rv;
 }
 
+void
+_shell_wm_confirm_display_change (ShellWM *wm)
+{
+  g_signal_emit (wm, shell_wm_signals[CONFIRM_DISPLAY_CHANGE], 0);
+}
+
 /**
  * shell_wm_new:
  * @plugin: the #MetaPlugin
index 20b740a3b9c395ad20a6561d85f57d14cb2287fe..778af523ea727e02c0ff21816ab9814c8379867c 100644 (file)
@@ -39,6 +39,9 @@ void     shell_wm_completed_destroy          (ShellWM         *wm,
                                               MetaWindowActor *actor);
 void     shell_wm_completed_switch_workspace (ShellWM         *wm);
 
+void     shell_wm_complete_display_change    (ShellWM         *wm,
+                                              gboolean         ok);
+
 G_END_DECLS
 
 #endif /* __SHELL_WM_H__ */